<?php

namespace app\api\controller;

use app\common\model\Grade;
use app\common\tools\RedisDB;
use think\facade\Log;
use Throwable;
use ba\Captcha;
use ba\ClickCaptcha;
use think\facade\Config;
use app\common\facade\Token;
use app\common\controller\Frontend;
use app\api\validate\User as UserValidate;

class System extends Frontend
{
    protected array $noNeedLogin = ['getJsSdkConfig'];

    private $appId;
    private $appSecret;

    public function initialize(): void
    {
        $this->appId = env('wechat.appid');
        $this->appSecret = env('wechat.secret');
        parent::initialize();
    }


    /**
     * 获取并缓存全局 Access Token
     * @return string
     * @throws \Exception
     */
    public function getAccessToken()
    {
        $cacheKey = 'wechat:access_token:' . env('wechat.appid');
        $redis = RedisDB::instance()->handler();
        $accessToken = $redis->get($cacheKey);
        if (!$accessToken) {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
            $response = makeRequest($url);


            if (isset($response['access_token'])) {
                $accessToken = $response['access_token'];
                // 缓存 access_token，并提前5分钟过期
                $redis->setex($cacheKey, $response['expires_in'] - 300, $accessToken);
            } else {
                Log::write('获取 Access Token 失败:'. ($response['errmsg'] ?? '未知错误'));
                $this->error('获取 Access Token 失败:');
            }
        }
        return $accessToken;
    }

    /**
     * 获取并缓存 JsApi Ticket
     * @return string
     * @throws \Exception
     */
    public function getJsApiTicket()
    {
        $cacheKey = 'wechat:jsapi_ticket:' . $this->appId;
        $redis = RedisDB::instance()->handler();
        $ticket = $redis->get($cacheKey);
        if (!$ticket) {
            $accessToken = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi";
            $response = makeRequest($url);

            if (isset($response['ticket'])) {
                $ticket = $response['ticket'];

                $redis->setex($cacheKey, $response['expires_in'] - 300, $ticket);
            } else {

                Log::write('获取 JsApi Ticket 失败: ' . ($result['errmsg'] ?? '未知错误'));
                $this->error('获取 JsApi Ticket 失败:');
            }
        }
        return $ticket;
    }


    /**
     * 获取 JSSDK 配置数组
     */
    public function getJsSdkConfig()
    {
        // 1. 获取所有必需的参数
        $jsapi_ticket = $this->getJsApiTicket();
        $timestamp = time();
        $nonceStr = bin2hex(random_bytes(16));
        $url = $this->request->post('url'); // 从前端获取原始URL
// 步骤1: 将所有待签名参数放入一个数组
        // 注意：所有参数名均为小写字符
        $params = [
            'noncestr' => $nonceStr,
            'jsapi_ticket' => $jsapi_ticket,
            'timestamp' => $timestamp,
            'url' => urldecode($url),
        ];

        // 步骤2: 对所有待签名参数按照字段名的ASCII码从小到大排序（字典序）
        ksort($params, SORT_STRING);

        // 步骤3: 使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串string1
        $stringParts = [];
        foreach ($params as $key => $value) {
            // 字段名和字段值都采用原始值，不进行URL转义
            $stringParts[] = "{$key}={$value}";
        }
        $stringToSign = implode('&', $stringParts);

        // 步骤4: 对string1作sha1加密
        $signature = sha1($stringToSign);

        $this->success('success', [
            'appId'     => $this->appId,
            'timestamp' => $timestamp,
            'nonceStr'  => $nonceStr,
            'signature' => $signature,
        ]);
    }
}
